package com.glepoch.springbootsecuritymybatis.compoment.constant.dict;


import com.glepoch.springbootsecuritymybatis.utils.CopyBeanUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: 根据传入的对象自动转换为目标对象的字典值，或者值转键。本工具类只支持number <--->String的相互转换
 * @codeTodesc true 为code转换为value false为value转换为code
 * @T 目标转换的类型
 * @author: ygl
 * @time: 2020/12/4 21:16
 */
public class DictUtils<T> {
    private List<T> targers = null;
    private boolean codeTodesc; //true 为code转换为value false为value转换为code

    public DictUtils(boolean isCodeTodesc) {
        this.targers = new ArrayList<>();
        this.codeTodesc = isCodeTodesc;
    }

    private DictUtils() {
    }

    /*
     * @sources  需要转换的对象组
     * @targerClazz 转换为目标对象
     * @dictEnum  需要转换的枚举对象（字典），枚举类需要实现IBaseDictEnum接口
     * */
    public List<T> convert(List sources, Class targerClazz, CommontDictEnum... dictEnum) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
        for (Object sourceObj : sources) {
            //通过传入targerClazz创建对象

            //用spring工具拷贝属性

            Object targerObj = CopyBeanUtils.beanToBean(sourceObj, targerClazz);
            //获取原对象的类对象
            Class<?> sourceClazz = sourceObj.getClass();
            //循环需要转换的字典
            for (CommontDictEnum commontDictEnum : dictEnum) {
                String dictFieldName = commontDictEnum.getField().toLowerCase();
                String dictCode = commontDictEnum.getCode();
                String dictDesc = commontDictEnum.getDesc();
                try {
                    //根据字段名称获取原对象的属性
                    Field sourceField = sourceClazz.getDeclaredField(dictFieldName);
                    Field targerField = targerClazz.getDeclaredField(dictFieldName);
                    if(sourceField==null){
                        continue;
                    }
                    //开启provide属性的访问权限
                    sourceField.setAccessible(true);
                    targerField.setAccessible(true);
                    //获取此属性的属性值
                    Object sourceFieldValueObj = sourceField.get(sourceObj);
                    Object targerFieldValueObj = targerField.get(targerObj);
                    String sourceFieldValueStr = "";
                    if (sourceFieldValueObj != null)
                        sourceFieldValueStr = String.valueOf(sourceFieldValueObj);
                    else
                        continue;  //为空不需要转换，直接跳过
                    if (codeTodesc&&targerFieldValueObj!=null&&targerFieldValueObj.equals(dictDesc)) { //字典与属性不同的直接跳过
                        continue;
                    }else if(!codeTodesc&&targerFieldValueObj!=null&&targerFieldValueObj.equals(dictCode)){
                        continue;
                    }
                    String firstUpCaseFieldName = dictFieldName.substring(0, 1).toUpperCase() + dictFieldName.substring(1).toLowerCase();
                    String getFieldName = "get" + firstUpCaseFieldName;
                    String setFieldName = "set" + firstUpCaseFieldName;
                    //codetodesc
                    if (codeTodesc && dictFieldName.equalsIgnoreCase(sourceField.getName()) && sourceFieldValueStr.equals(dictCode)) {
                        //通过get方法
                        Method targerGetmethod = targerClazz.getMethod(getFieldName);
                        //获取返回值类型
                        Class<?> targerreturnType = targerGetmethod.getReturnType();
                        //获取set方法
                        Method targerSetmethod = targerClazz.getMethod(setFieldName, targerreturnType);
                        targerSetmethod.invoke(targerObj, dictDesc);
                        System.out.println(dictFieldName + "--->" + sourceFieldValueStr);
                        //desctocode
                    } else if (!codeTodesc && dictFieldName.equalsIgnoreCase(sourceField.getName()) && sourceFieldValueStr.equals(dictDesc)) {
                        //通过get方法
                        Method targerGetmethod = targerClazz.getMethod(getFieldName);
                        //获取返回值类型
                        Class<?> targerreturnType = targerGetmethod.getReturnType();
                        String targerreturnTypeName = targerreturnType.getCanonicalName();

                        //获取set方法
                        Method targerSetmethod = targerClazz.getMethod(setFieldName, targerreturnType);
                        //descToCode有可能会出现字符串-->数字的情况，估需要对返回值类型进行判断
                        Object targerDictCode = null;
                        if (targerreturnTypeName.equals("int")) {
                            targerDictCode = Integer.valueOf(dictCode);
                        } else if (targerreturnTypeName.equals("long")) {
                            targerDictCode = Long.valueOf(dictCode);
                        } else if (targerreturnTypeName.equals("float")) {
                            targerDictCode = Float.valueOf(dictCode);
                        } else if (targerreturnTypeName.equals("double")) {
                            targerDictCode = Double.valueOf(dictCode);
                        } else {
                            targerDictCode = dictCode;
                        }
                        System.out.println(targerreturnType.getCanonicalName());
                        targerSetmethod.invoke(targerObj, targerDictCode);
                        System.out.println(dictFieldName + "--->" + sourceFieldValueStr);
                    }
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                }
            }
            targers.add((T) targerObj);
        }
        return targers;
    }


    /*
     * @sources  需要转换的对象组
     * @targerClazz 转换为目标对象
     * @iBaseDictEnum  需要转换的枚举对象（字典），枚举类需要实现IBaseDictEnum接口
     * */
    public List<T> convert(List sources, Class targerClazz, Class iBaseDictEnum) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException {
        for (Object sourceObj : sources) {
            //通过传入targerClazz创建对象
            //Object targerObj = targerClazz.newInstance();
            //用spring工具拷贝属性
            Object targerObj = CopyBeanUtils.beanToBean(sourceObj, targerClazz);
            //获取原对象的类对象
            Class<?> sourceClazz = sourceObj.getClass();
            Field[] sourceClazzDeclaredFields = sourceClazz.getDeclaredFields();
            for (Field sourceClazzDeclaredField : sourceClazzDeclaredFields) {
                sourceClazzDeclaredField.setAccessible(true);
                String sourceClazzDeclaredFieldName = sourceClazzDeclaredField.getName();
                Field targerClazzDeclaredField = targerClazz.getDeclaredField(sourceClazzDeclaredFieldName);
                targerClazzDeclaredField.setAccessible(true);
                Object sourceClazzDeclaredFieldValue = sourceClazzDeclaredField.get(sourceObj);
                Object targerClazzDeclaredFieldValue = targerClazzDeclaredField.get(targerObj);
                String sourceValueStr = "";
                String targetValueStr = "";
                if (sourceClazzDeclaredFieldValue != null)
                    sourceValueStr = sourceClazzDeclaredFieldValue.toString();
                else
                    continue;
                if (targerClazzDeclaredFieldValue != null)
                    targetValueStr = targerClazzDeclaredFieldValue.toString();
                Object dictObj = null;
                if (codeTodesc)
                    dictObj = getDescFromEnum(iBaseDictEnum, sourceClazzDeclaredFieldName, sourceValueStr);
                else
                    dictObj = getCodeFromEnum(iBaseDictEnum, sourceClazzDeclaredFieldName, sourceValueStr);
                if (!dictObj.equals(targerClazzDeclaredFieldValue)) {
                    String firstUpCaseFieldName = sourceClazzDeclaredFieldName.substring(0, 1).toUpperCase() + sourceClazzDeclaredFieldName.substring(1).toLowerCase();
                    String getFieldName = "get" + firstUpCaseFieldName;
                    String setFieldName = "set" + firstUpCaseFieldName;
                    //codetodesc
                    if (codeTodesc) {
                        //通过get方法
                        Method targerGetmethod = targerClazz.getMethod(getFieldName);
                        //获取返回值类型
                        Class<?> targerreturnType = targerGetmethod.getReturnType();
                        //获取set方法
                        Method targerSetmethod = targerClazz.getMethod(setFieldName, targerreturnType);
                        targerSetmethod.invoke(targerObj, dictObj);

                        //desctocode
                    } else if (!codeTodesc) {
                        //通过get方法
                        Method targerGetmethod = targerClazz.getMethod(getFieldName);
                        //获取返回值类型
                        Class<?> targerreturnType = targerGetmethod.getReturnType();
                        String targerreturnTypeName = targerreturnType.getCanonicalName();

                        //获取set方法
                        Method targerSetmethod = targerClazz.getMethod(setFieldName, targerreturnType);
                        //descToCode有可能会出现字符串-->数字的情况，估需要对返回值类型进行判断
                        Object targerDictCode = null;
                        if (targerreturnTypeName.equals("int")) {
                            targerDictCode = Integer.valueOf(dictObj.toString());
                        } else if (targerreturnTypeName.equals("long")) {
                            targerDictCode = Long.valueOf(dictObj.toString());
                        } else if (targerreturnTypeName.equals("float")) {
                            targerDictCode = Float.valueOf(dictObj.toString());
                        } else if (targerreturnTypeName.equals("double")) {
                            targerDictCode = Double.valueOf(dictObj.toString());
                        } else {
                            targerDictCode = dictObj;
                        }
                        targerSetmethod.invoke(targerObj, targerDictCode);
                    }
                } else {
                    continue;
                }

            }


            targers.add((T) targerObj);
        }
        return targers;
    }
    //通过desc获取字典的code
    private Object getCodeFromEnum(Class iBaseDictEnum, String field, String desc) {
        Object[] enumConstants = iBaseDictEnum.getEnumConstants();
        for (Object enumConstant : enumConstants) {
            if (enumConstant instanceof IBaseDictEnum) {
                IBaseDictEnum dictEnum = (IBaseDictEnum) enumConstant;
                if (dictEnum.getField().equals(field) && dictEnum.getDesc().equals(desc)) {
                    return dictEnum.getCode();
                }
            }
        }
        return null;
    }
    //通过code获取字典的desc
    private String getDescFromEnum(Class iBaseDictEnum, String field, String code) {
        Object[] enumConstants = iBaseDictEnum.getEnumConstants();
        for (Object enumConstant : enumConstants) {
            if (enumConstant instanceof IBaseDictEnum) {
                IBaseDictEnum dictEnum = (IBaseDictEnum) enumConstant;
                if (dictEnum.getField().equals(field) && dictEnum.getCode().equals(code)) {
                    return dictEnum.getDesc();
                }
            }
        }
        return null;
    }
}
